package com.im.server.handle;

import com.im.common.toolkit.SpringUtils;
import com.im.server.protocol.MessageProto;
import com.im.server.session.SessionSocketHolder;
import com.im.web.core.model.ChatMessage;
import com.im.web.core.repository.ChatMessageRepository;
import io.netty.channel.*;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

import static com.im.common.Constants.CommandType.LOGIN;
import static com.im.common.Constants.CommandType.MESSAGE;
import static com.im.common.Constants.*;

/**
 * @author gongym
 * @date 2019/1/9 13:07
 */
@ChannelHandler.Sharable
public class ImServerHandle extends SimpleChannelInboundHandler<MessageProto.MessageProtocol> {
  private static final Logger LOGGER = LoggerFactory.getLogger(ImServerHandle.class);
  /** 客户端与服务端会话连接成功 */
  @Override
  public void channelActive(ChannelHandlerContext ctx) throws Exception {
    super.channelActive(ctx);
  }

  @Override
  public void channelInactive(ChannelHandlerContext ctx) {
    // 用户下线清除通道保存
    SessionSocketHolder.removeChannel((NioSocketChannel) ctx.channel());
  }

  @Override
  protected void channelRead0(
      ChannelHandlerContext channelHandlerContext, MessageProto.MessageProtocol message) {
    int type = message.getType();
    if (LOGIN == type) {
      // 每个客户端初始化WebSocket连接时都会发送登录消息
      LOGGER.info("[接收]客户端登录消息：{}", message.toString());
      // 保存客户端与 Channel 之间的关系
      SessionSocketHolder.putChannel(
          message.getFrom(), (NioSocketChannel) channelHandlerContext.channel());
    } else if (MESSAGE == type) {
      LOGGER.info("[接收]客户端发送消息：{}", message.toString());
      // 开始处理消息
      long from = message.getFrom();
      long to = message.getTo();
      // 给服务器发消息，应该是机器人分析后回复，暂时原样回复
      NioSocketChannel nioSocketChannel = SessionSocketHolder.getChannel(from);
      if (null == nioSocketChannel) {
        // 发送离线消息
        LOGGER.info("客户端[" + from + "]不在线！");
      } else {
        // 处理各种客户端消息，然后返回
        MessageProto.MessageProtocol messageProtocol;
        if (to == TO_SERVER) {
          String handleMessageClass = MESSAGE_HANDLE_MAP.get(TO_SERVER);
          MessageService messageService =
              SpringUtils.getBean(handleMessageClass, MessageService.class);
          messageProtocol = messageService.handleMessage(message);
        } else {
          String handleMessageClass = MESSAGE_HANDLE_MAP.get(TO_USER);
          MessageService messageService =
              SpringUtils.getBean(handleMessageClass, MessageService.class);
          messageProtocol = messageService.handleMessage(message);
        }
        ChannelFuture future = nioSocketChannel.writeAndFlush(messageProtocol);
        future.addListener(
            (ChannelFutureListener)
                channelFuture -> {
                  ChatMessageRepository chatMessageRepository =
                      SpringUtils.getBean(ChatMessageRepository.class);
                  ChatMessage fromChatMessage = new ChatMessage();
                  fromChatMessage.setFromId(messageProtocol.getFrom());
                  fromChatMessage.setToId(messageProtocol.getTo());
                  fromChatMessage.setChatType(messageProtocol.getType());
                  fromChatMessage.setCreateTime(new Date(messageProtocol.getCreateTime()));
                  fromChatMessage.setChatContent(messageProtocol.getContent());
                  chatMessageRepository.save(fromChatMessage);
                  LOGGER.info("[发送]服务端消息成功={}", messageProtocol.toString());
                });
      }
    }
  }

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {}
}
